#include <system.h>
#include <drivers/input/mouse.h>

static unsigned int detect_ps2_mouse();
static unsigned int ps2_mouse();

signed char mouse_x=0;         //signed char
signed char mouse_y=0;         //signed char

/*
u8 inb(u16 port)
{
    u8 ret;
    __asm__ __volatile__("inb %1, %0" : "=a" (ret) : "dN" (port));
    return ret;
}*/

    void mouse_handler(struct regs *r)
    {
      static unsigned char cycle = 0;
      static char mouse_bytes[3];
      mouse_bytes[cycle++] = inportb(0x60);
     
      if (cycle == 3) { // if we have all the 3 bytes...
        cycle = 0; // reset the counter
        // do what you wish with the bytes, this is just a sample
        if ((mouse_bytes[0] & 0x80) || (mouse_bytes[0] & 0x40))
          return; // the mouse only sends information about overflowing, do not care about it and return
        if (!(mouse_bytes[0] & 0x20))
          mouse_y |= 0xFFFFFF00; //delta-y is a negative value
        if (!(mouse_bytes[0] & 0x10))
          mouse_x |= 0xFFFFFF00; //delta-x is a negative value
        if (mouse_bytes[0] & 0x4)
          puts("Middle button is pressed!n");
        if (mouse_bytes[0] & 0x2)
          puts("Right button is pressed!n");
        if (mouse_bytes[0] & 0x1)
          puts("Left button is pressed!n");
		
	      mouse_x=mouse_bytes[1];
	      mouse_y=mouse_bytes[2];
	printf("cords %d and %d\n",mouse_x,mouse_y);
        // do what you want here, just replace the puts's to execute an action for each button
        // to use the coordinate data, use mouse_bytes[1] for delta-x, and mouse_bytes[2] for delta-y
      }
    }


static unsigned int ps2_mouse(void)
{
	return 1;
}

static void mouse_wait(unsigned char a_type)
{
  unsigned int _time_out=100000;
  if(a_type==0)
  {
    while(_time_out--) //Data
    {
      if((inportb(0x64) & 1)==1)
      {
        return;
      }
    }
    return;
  }
  else
  {
    while(_time_out--) //Signal
    {
      if((inportb(0x64) & 2)==0)
      {
        return;
      }
    }
    return;
  }
}

static unsigned char mouse_read()
{
  //Get's response from mouse
  mouse_wait(0);
  return inportb(0x60);
}

void mouse_write(unsigned char a_write)
{
//Wait to be able to send a command
mouse_wait(1);
//Tell the mouse we are sending a command
outportb(0x64, 0xD4);
//Wait for the final part
mouse_wait(1);
//Finally write
outportb(0x60, a_write);
}

void ps2mouse_install(void)
{
  byte _status;  //unsigned char

  //Enable the auxiliary mouse device
  mouse_wait(1);
  outportb(0x64, 0xA8);
 
  //Enable the interrupts
  mouse_wait(1);
  outportb(0x64, 0x20);
  mouse_wait(0);
  _status=(inportb(0x60) | 2);
  mouse_wait(1);
  outportb(0x64, 0x60);
  mouse_wait(1);
  outportb(0x60, _status);
 
  //Tell the mouse to use default settings
  mouse_write(0xF6);
  mouse_read();  //Acknowledge
 
  //Enable the mouse
  mouse_write(0xF4);
  mouse_read();  //Acknowledge

  //Setup the mouse handler
  irq_install_handler(12, mouse_handler);
}

static unsigned int detect_ps2_mouse(void)
{
    /*unsigned char tmp = mouse_read();
    if(tmp != 0xFA)
         return 0; //Return no mouse detected
    else */
         return 1; //Return mouse detected
}


MouseDriver PS2_driver =
{
	detect_ps2_mouse,
	ps2mouse_install
};


char Check_PS2M(MouseDriver * driver)
{
	*driver = PS2_driver;
	return (detect_ps2_mouse());
}
